Note: This analysis requires input data generated by an earlier script.

Setup

  • Clear memory and console
  • Load packages
  • Get current script name
# Clear memory
rm(list=setdiff(ls(all=TRUE), c(".Random.seed")))
# Clear console
cat("\014")

Set up

this.script <- rstudioapi::getActiveDocumentContext()$path %>% basename
cat("Script:", this.script)
Script: 07_Figure_S1_B.Rmd
gg.get.breaks_by1 <- function(limits) {
  a <- floor(limits[1])
  b <- ceiling(limits[2])
  seq(a, b, by = 1)
}

gg.get.breaks_by2 <- function(limits) {
  a <- floor(limits[1])
  if (a %% 2 == 1) a <- a - 1
  b <- ceiling(limits[2])
  if (b %% 2 == 1) b <- b + 1
  seq(a, b, by = 2)
}
get.gg <- function(mtrx, colum.names, axis.labs, titre,
                    marker.col.false, marker.col.true="#B20000", marker.alpha=1, ttable) {

  ttable2 <- dplyr::select(ttable, PROBEID, SYMBOL, adj.P.Val) %>% 
    dplyr::group_by(PROBEID) %>%
    dplyr::slice(which.min(adj.P.Val)) %>% 
    dplyr::ungroup(.)

  df <- mtrx[,colum.names] %>% 
    magrittr::set_colnames(axis.labs) %>% 
    tibble::rownames_to_column("PROBEID")
  
  df2 <- merge(x=ttable2, y=df, by="PROBEID", all.x=FALSE, all.y=TRUE) %>% 
    dplyr::mutate(p.ok = adj.P.Val <= 0.05) %>% 
    dplyr::mutate(p.ok = as.character(p.ok)) %>% 
    dplyr::mutate(p.ok = factor(p.ok, levels=c("FALSE", "TRUE"))) %>% 
    dplyr::mutate(ID = paste0(SYMBOL, " (", PROBEID, ")")) %>% 
    dplyr::select(-PROBEID, -SYMBOL, -adj.P.Val) %>% 
    dplyr::select(ID, everything())

  res <- df2 %>% 
    ggplot(aes_string(x=axis.labs[1], y=axis.labs[2])) +
    geom_point(aes(text=ID, color=p.ok), alpha=marker.alpha) + # color=marker.col.false,
    # scale_color_discrete(name="p ≤ 0.05") +
    scale_color_manual(values=c(marker.col.false, marker.col.true), name="p ≤ 0.05") +
    scale_x_continuous(limits =c(min(mtrx), max(mtrx))) +
    scale_y_continuous(limits =c(min(mtrx), max(mtrx))) +
    geom_abline(intercept = 0, slope = 1, color="grey25") +
    geom_abline(intercept = -log2(1.75), slope = 1, color="grey25", linetype="dashed") +
    geom_abline(intercept = log2(1.75), slope = 1, color="grey25", linetype="dashed") +
    labs(title = titre)
  res
}

Load data

Load mean expression data

Table includes probe IDs, gene symbols and gene names.
Probe IDs and symbols are not unique (due to gene symbol mapping).

mean.expr.file <- "./data/01_Raw_Data_Processing.Rmd.expr_mean.txt"
matrix.df.mean <- read.table(mean.expr.file, sep="\t", header=T,
                             stringsAsFactors = FALSE) %>% 
  dplyr::select(-SYMBOL, -GENENAME) %>% 
  dplyr::distinct(PROBEID, .keep_all=TRUE) %>% 
  tibble::column_to_rownames("PROBEID")
cat("File read:", mean.expr.file)
File read: ./data/01_Raw_Data_Processing.Rmd.expr_mean.txt
rm(mean.expr.file)

Load differentially expressed probes (effect of MMS)

# list.files("data")
diff.probes.file <- "./data/02_Suppl_Table_01.Rmd.DEprobes.RDS"
stopifnot(file.exists(diff.probes.file))
test.results.probes <- readRDS(diff.probes.file)
cat("File read:", diff.probes.file)
File read: ./data/02_Suppl_Table_01.Rmd.DEprobes.RDS
rm(diff.probes.file)
x <- paste(utils::capture.output(str(test.results.probes)), collapse="<br>\n", sep="")
details::details(x, summary="Show summary of DE probes", lang=NULL)
Show summary of DE probes

List of 4
$ ko.ctrl.vs.wt.ctrl:List of 3
..$ down : chr [1:5] “1419620_at” “1424105_a_at” “1425771_at” “1438390_s_at” …
..$ up : chr [1:4] “1416958_at” “1426230_at” “1426464_at” “1438211_s_at”
..$ total: chr [1:9] “1416958_at” “1419620_at” “1424105_a_at” “1425771_at” …
$ ko.mms.vs.wt.mms :List of 3
..$ down : chr [1:3] “1419620_at” “1424105_a_at” “1438390_s_at”
..$ up : chr “1455530_at”
..$ total: chr [1:4] “1419620_at” “1424105_a_at” “1438390_s_at” “1455530_at”
$ wt.mms.vs.wt.ctrl :List of 3
..$ down : chr [1:584] “1415743_at” “1415802_at” “1415810_at” “1415822_at” …
..$ up : chr [1:232] “1416029_at” “1416108_a_at” “1416235_at” “1416432_at” …
..$ total: chr [1:816] “1415743_at” “1415802_at” “1415810_at” “1415822_at” …
$ ko.mms.vs.ko.ctrl :List of 3
..$ down : chr [1:105] “1415972_at” “1416158_at” “1417020_at” “1417073_a_at” …
..$ up : chr [1:115] “1415817_s_at” “1416100_at” “1416172_at” “1416347_at” …
..$ total: chr [1:220] “1415817_s_at” “1415972_at” “1416100_at” “1416158_at” …


rm(x)

Load toptables

# list.files()
tt.file <- "Supplemental_Data_1.xlsx"
stopifnot(file.exists(tt.file))
tt.sheet.names <- openxlsx::getSheetNames(tt.file)
# tt.sheet.names
# "ko.ctrl.vs.wt.ctrl" "ko.mms.vs.wt.mms"   "wt.mms.vs.wt.ctrl"  "ko.mms.vs.ko.ctrl"
get.xlsx.data <- function(fil, sheet) {
  openxlsx::read.xlsx(xlsxFile = fil, sheet=sheet)
}
tt.list <- lapply(tt.sheet.names, function(the.sheet) {
  res <- get.xlsx.data(fil=tt.file, sheet=the.sheet) %>% 
    dplyr::select(PROBEID, SYMBOL, logFC, adj.P.Val)
  res
}) %>% 
  set_names(tt.sheet.names)
cat("File read:", tt.file)
File read: Supplemental_Data_1.xlsx
rm(tt.file, tt.sheet.names)
y <- paste(utils::capture.output(str(tt.list)), collapse="<br>\n", sep="")
details::details(y, summary="Show summary of toptables list", lang=NULL)
Show summary of toptables list

List of 4
$ ko.ctrl.vs.wt.ctrl:‘data.frame’: 24491 obs. of 4 variables:
..$ PROBEID : chr [1:24491] “1439200_x_at” “1426464_at” “1438211_s_at” “1455265_a_at” …
..$ SYMBOL : chr [1:24491] “Rhox4b” “Nr1d1” “Dbp” “Rgs16” …
..$ logFC : num [1:24491] 4.19 3.6 3.36 3.33 3.26 …
..$ adj.P.Val: num [1:24491] 0.35717 0.00159 0.04513 0.41762 0.50034 …
$ ko.mms.vs.wt.mms :‘data.frame’: 24491 obs. of 4 variables:
..$ PROBEID : chr [1:24491] “1439200_x_at” “1415905_at” “1434137_x_at” “1448964_at” …
..$ SYMBOL : chr [1:24491] “Rhox4b” “Reg1” “Zg16” “S100g” …
..$ logFC : num [1:24491] 4 3.48 3.42 2.97 2.47 …
..$ adj.P.Val: num [1:24491] 0.0941 0.1387 0.2036 0.1737 0.3266 …
$ wt.mms.vs.wt.ctrl :‘data.frame’: 24491 obs. of 4 variables:
..$ PROBEID : chr [1:24491] “1438211_s_at” “1428942_at” “1455265_a_at” “1449233_at” …
..$ SYMBOL : chr [1:24491] “Dbp” “Mt2” “Rgs16” “Bhlha15” …
..$ logFC : num [1:24491] 4.33 4.23 4.2 4.17 4 …
..$ adj.P.Val: num [1:24491] 0.00214 0.00594 0.01936 0.02318 0.00214 …
$ ko.mms.vs.ko.ctrl :‘data.frame’: 24491 obs. of 4 variables:
..$ PROBEID : chr [1:24491] “1415905_at” “1448964_at” “1418287_a_at” “1434137_x_at” …
..$ SYMBOL : chr [1:24491] “Reg1” “S100g” “Dmbt1” “Zg16” …
..$ logFC : num [1:24491] 4.15 3.91 3.48 3.46 3.39 …
..$ adj.P.Val: num [1:24491] 0.0582 0.0638 0.0832 0.129 0.1372 …


rm(y)

Plot probes suppressed OR induced by MMS in wild-type OR knockout

Select probes to plot

wt.ko.down.up <- sort(unique(unlist(test.results.probes)))
stopifnot(!any(is.na(wt.ko.down.up)))
cat("Probes selected:", length(wt.ko.down.up))
Probes selected: 980
# matrix.df.mean[1:4,1:4]
mx.wt.ko.down.up <- matrix.df.mean[wt.ko.down.up,]
dim(mx.wt.ko.down.up)
gg.6.4 <- get.gg(mtrx=mx.wt.ko.down.up,
       colum.names = c("Wt_Ctrl", "Ko_Ctrl"),
       axis.labs = c("WT", "KO"),
       titre = "Control: Knockout versus Wild-type",
       marker.col.false = "#005AB5", # bp[3]
       marker.col.true = "#DC3220",
       marker.alpha=0.5,
       ttable=tt.list$ko.ctrl.vs.wt.ctrl)
gg.6.4b <- gg.6.4 + 
  theme_classic() +
  coord_equal()
ggplotly(gg.6.4b)

Save plot

out.file.pdf <- "Figure_S1_B.pdf"
ggsave(filename=out.file.pdf, plot = gg.6.4b, width = 10, height=10, units = "cm")
cat("Saved:", out.file.pdf)
Saved: Figure_S1_B.pdf

Session info

cat("Date:", format(Sys.time(), "%a %d-%b-%Y %H:%M:%S"), "<br>\n")

Date: Mon 21-Jun-2021 08:46:46

devtools::session_info()
─ Session info ────────────────────────────────────────────────────────────────────────────────────

─ Packages ────────────────────────────────────────────────────────────────────────────────────────
 package        * version date       lib source        
 affy             1.64.0  2019-10-29 [1] Bioconductor  
 affyio           1.56.0  2019-10-29 [1] Bioconductor  
 AnnotationDbi  * 1.48.0  2019-10-29 [1] Bioconductor  
 assertthat       0.2.1   2019-03-21 [1] CRAN (R 3.6.1)
 Biobase        * 2.46.0  2019-10-29 [1] Bioconductor  
 BiocGenerics   * 0.32.0  2019-10-29 [1] Bioconductor  
 BiocManager      1.30.12 2021-03-28 [1] CRAN (R 3.6.1)
 bit              4.0.4   2020-08-04 [1] CRAN (R 3.6.1)
 bit64            4.0.5   2020-08-30 [1] CRAN (R 3.6.1)
 blob             1.2.1   2020-01-20 [1] CRAN (R 3.6.1)
 bslib            0.2.4   2021-01-25 [1] CRAN (R 3.6.1)
 cachem           1.0.4   2021-02-13 [1] CRAN (R 3.6.1)
 callr            3.6.0   2021-03-28 [1] CRAN (R 3.6.1)
 cellranger       1.1.0   2016-07-27 [1] CRAN (R 3.6.1)
 cli              2.3.1   2021-02-23 [1] CRAN (R 3.6.1)
 clipr            0.7.1   2020-10-08 [1] CRAN (R 3.6.1)
 codetools        0.2-16  2018-12-24 [2] CRAN (R 3.6.1)
 colorspace       2.0-0   2020-11-11 [1] CRAN (R 3.6.1)
 crayon           1.4.1   2021-02-08 [1] CRAN (R 3.6.1)
 crosstalk        1.1.1   2021-01-12 [1] CRAN (R 3.6.1)
 data.table       1.14.0  2021-02-21 [1] CRAN (R 3.6.1)
 DBI              1.1.1   2021-01-15 [1] CRAN (R 3.6.1)
 debugme          1.1.0   2017-10-22 [1] CRAN (R 3.6.1)
 desc             1.3.0   2021-03-05 [1] CRAN (R 3.6.1)
 details          0.2.1   2020-01-12 [1] CRAN (R 3.6.1)
 devtools         2.3.2   2020-09-18 [1] CRAN (R 3.6.1)
 digest           0.6.27  2020-10-24 [1] CRAN (R 3.6.1)
 dplyr          * 1.0.5   2021-03-05 [1] CRAN (R 3.6.1)
 DT               0.17    2021-01-06 [1] CRAN (R 3.6.1)
 ellipsis         0.3.1   2020-05-15 [1] CRAN (R 3.6.1)
 evaluate         0.14    2019-05-28 [1] CRAN (R 3.6.1)
 fansi            0.4.2   2021-01-15 [1] CRAN (R 3.6.1)
 farver           2.1.0   2021-02-28 [1] CRAN (R 3.6.1)
 fastmap          1.1.0   2021-01-25 [1] CRAN (R 3.6.1)
 fs               1.5.0   2020-07-31 [1] CRAN (R 3.6.1)
 generics         0.1.0   2020-10-31 [1] CRAN (R 3.6.1)
 ggplot2        * 3.3.3   2020-12-30 [1] CRAN (R 3.6.1)
 glue             1.4.2   2020-08-27 [1] CRAN (R 3.6.1)
 gridExtra        2.3     2017-09-09 [1] CRAN (R 3.6.1)
 gtable           0.3.0   2019-03-25 [1] CRAN (R 3.6.1)
 htmltools        0.5.1.1 2021-01-22 [1] CRAN (R 3.6.1)
 htmlwidgets      1.5.3   2020-12-10 [1] CRAN (R 3.6.1)
 httr             1.4.2   2020-07-20 [1] CRAN (R 3.6.1)
 IRanges        * 2.20.2  2020-01-13 [1] Bioconductor  
 jquerylib        0.1.3   2020-12-17 [1] CRAN (R 3.6.1)
 jsonlite         1.7.2   2020-12-09 [1] CRAN (R 3.6.1)
 knitr            1.31    2021-01-27 [1] CRAN (R 3.6.1)
 labeling         0.4.2   2020-10-20 [1] CRAN (R 3.6.1)
 lazyeval         0.2.2   2019-03-15 [1] CRAN (R 3.6.1)
 lifecycle        1.0.0   2021-02-15 [1] CRAN (R 3.6.1)
 limma            3.42.2  2020-02-03 [1] Bioconductor  
 magrittr       * 2.0.1   2020-11-17 [1] CRAN (R 3.6.1)
 memoise          2.0.0   2021-01-26 [1] CRAN (R 3.6.1)
 mouse430a2.db  * 3.2.3   2021-03-28 [1] Bioconductor  
 munsell          0.5.0   2018-06-12 [1] CRAN (R 3.6.1)
 openxlsx         4.2.3   2020-10-27 [1] CRAN (R 3.6.1)
 org.Mm.eg.db   * 3.10.0  2021-03-28 [1] Bioconductor  
 pillar           1.5.1   2021-03-05 [1] CRAN (R 3.6.1)
 pkgbuild         1.2.0   2020-12-15 [1] CRAN (R 3.6.1)
 pkgconfig        2.0.3   2019-09-22 [1] CRAN (R 3.6.1)
 pkgload          1.2.0   2021-02-23 [1] CRAN (R 3.6.1)
 plotly         * 4.9.3   2021-01-10 [1] CRAN (R 3.6.1)
 png              0.1-7   2013-12-03 [1] CRAN (R 3.6.1)
 preprocessCore   1.48.0  2019-10-29 [1] Bioconductor  
 prettyunits      1.1.1   2020-01-24 [1] CRAN (R 3.6.1)
 processx         3.5.0   2021-03-23 [1] CRAN (R 3.6.1)
 pryr             0.1.4   2018-02-18 [1] CRAN (R 3.6.1)
 ps               1.6.0   2021-02-28 [1] CRAN (R 3.6.1)
 purrr            0.3.4   2020-04-17 [1] CRAN (R 3.6.1)
 R6               2.5.0   2020-10-28 [1] CRAN (R 3.6.1)
 RColorBrewer     1.1-2   2014-12-07 [1] CRAN (R 3.6.1)
 Rcpp             1.0.6   2021-01-15 [1] CRAN (R 3.6.1)
 readxl           1.3.1   2019-03-13 [1] CRAN (R 3.6.1)
 remotes          2.2.0   2020-07-21 [1] CRAN (R 3.6.1)
 rlang            0.4.10  2020-12-30 [1] CRAN (R 3.6.1)
 rmarkdown        2.7     2021-02-19 [1] CRAN (R 3.6.1)
 rprojroot        2.0.2   2020-11-15 [1] CRAN (R 3.6.1)
 RSQLite          2.2.5   2021-03-27 [1] CRAN (R 3.6.1)
 rstudioapi       0.13    2020-11-12 [1] CRAN (R 3.6.1)
 S4Vectors      * 0.24.4  2020-04-09 [1] Bioconductor  
 sass             0.3.1   2021-01-24 [1] CRAN (R 3.6.1)
 scales         * 1.1.1   2020-05-11 [1] CRAN (R 3.6.1)
 sessioninfo      1.1.1   2018-11-05 [1] CRAN (R 3.6.1)
 stringi          1.5.3   2020-09-09 [1] CRAN (R 3.6.1)
 stringr          1.4.0   2019-02-10 [1] CRAN (R 3.6.1)
 superheat      * 0.1.0   2017-02-04 [1] CRAN (R 3.6.1)
 testthat         3.0.2   2021-02-14 [1] CRAN (R 3.6.1)
 tibble           3.1.0   2021-02-25 [1] CRAN (R 3.6.1)
 tidyr            1.1.3   2021-03-03 [1] CRAN (R 3.6.1)
 tidyselect       1.1.0   2020-05-11 [1] CRAN (R 3.6.1)
 usethis          2.0.1   2021-02-10 [1] CRAN (R 3.6.1)
 utf8             1.2.1   2021-03-12 [1] CRAN (R 3.6.1)
 vctrs            0.3.6   2020-12-17 [1] CRAN (R 3.6.1)
 viridisLite      0.3.0   2018-02-01 [1] CRAN (R 3.6.1)
 withr            2.4.1   2021-01-26 [1] CRAN (R 3.6.1)
 xfun             0.22    2021-03-11 [1] CRAN (R 3.6.1)
 xml2             1.3.2   2020-04-23 [1] CRAN (R 3.6.1)
 yaml             2.2.1   2020-02-01 [1] CRAN (R 3.6.1)
 zip              2.1.1   2020-08-27 [1] CRAN (R 3.6.1)
 zlibbioc         1.32.0  2019-10-29 [1] Bioconductor  

[1] /homedirs26/sghms/bms/users/anohturf/R/x86_64-pc-linux-gnu-library/3.6
[2] /usr/local/R-3.6.1/library
LS0tCnRpdGxlOiAiQSBub3ZlbCByb2xlIGZvciBhbGt5bGFkZW5pbmUgRE5BIGdseWNvc3lsYXNlIGluIHJlZ3VsYXRpbmcgYWxreWxhdGlvbi1pbmR1Y2VkIEVSIHN0cmVzcyIKc3VidGl0bGU6ICJGaWd1cmUgUzEsIFBhbmVsIEIiCmF1dGhvcjogIkwgTWlsYW5vLCBDRiBDaGFybGllciwgUiBBbmRyZWd1ZXR0aSwgVCBDb3gsIEUgSGVhbGluZywgTVAgVGhvbcOpLCBSTSBFbGxpb3R0LCBKWSBNYXNzb24sIExEIFNhbXNvbiwgSlkgTWFzc29uLCBHIExlbnosIEpBUCBIZW5yaXF1ZXMsIEEgTm9odHVyZmZ0IGFuZCBMQiBNZWlyYSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgdG9jX2RlcHRoOiAzCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgogICAgbnVtYmVyX3NlY3Rpb25zOiBGQUxTRQogICAgdGhlbWU6ICJyZWFkYWJsZSIKICAgIGhpZ2hsaWdodDogInRhbmdvIgogICAgZmlnX2NhcHRpb246IFRSVUUKICAgIGNzczogIi4vc291cmNlL3N0eWxlcy5jc3MiCi0tLQoKYGBge2pzfQpmdW5jdGlvbiBteUZ1bmN0aW9uKGlkKSB7CiAgdmFyIHggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7CiAgaWYgKHguc3R5bGUuZGlzcGxheSA9PT0gJ25vbmUnKSB7CiAgICB4LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snOwogIH0gZWxzZSB7CiAgICB4LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgfQp9CmBgYAoKPGRpdiBjbGFzcz0nY29tbWVudHMnPgpOb3RlOiBUaGlzIGFuYWx5c2lzIHJlcXVpcmVzIGlucHV0IGRhdGEgZ2VuZXJhdGVkIGJ5IGFuIGVhcmxpZXIgc2NyaXB0Lgo8L2Rpdj4KCiMjIFNldHVwICAKCiogQ2xlYXIgbWVtb3J5IGFuZCBjb25zb2xlICAKKiBMb2FkIHBhY2thZ2VzICAKKiBHZXQgY3VycmVudCBzY3JpcHQgbmFtZSAgCgpgYGB7ciBDTEVBUiBNRU1PUlkgQU5EIFBBQ0tBR0VTIEFORCBDT05TT0xFLCByZXN1bHRzPSJoaWRlIn0KIyBDbGVhciBtZW1vcnkKcm0obGlzdD1zZXRkaWZmKGxzKGFsbD1UUlVFKSwgYygiLlJhbmRvbS5zZWVkIikpKQojIENsZWFyIGNvbnNvbGUKY2F0KCJcMDE0IikKYGBgCgojIyBTZXQgdXAgIApgYGB7ciBQYWNrYWdlcywgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0iaGlkZSJ9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmBgYAoKCmBgYHtyIEdldCBzY3JpcHQgbmFtZSwgIGNsYXNzLm91dHB1dD0idHh0X291dHB1dCJ9CnRoaXMuc2NyaXB0IDwtIHJzdHVkaW9hcGk6OmdldEFjdGl2ZURvY3VtZW50Q29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lCmNhdCgiU2NyaXB0OiIsIHRoaXMuc2NyaXB0KQpgYGAKCgpgYGB7ciBGdW5jdGlvbnNfMX0KZ2cuZ2V0LmJyZWFrc19ieTEgPC0gZnVuY3Rpb24obGltaXRzKSB7CiAgYSA8LSBmbG9vcihsaW1pdHNbMV0pCiAgYiA8LSBjZWlsaW5nKGxpbWl0c1syXSkKICBzZXEoYSwgYiwgYnkgPSAxKQp9CgpnZy5nZXQuYnJlYWtzX2J5MiA8LSBmdW5jdGlvbihsaW1pdHMpIHsKICBhIDwtIGZsb29yKGxpbWl0c1sxXSkKICBpZiAoYSAlJSAyID09IDEpIGEgPC0gYSAtIDEKICBiIDwtIGNlaWxpbmcobGltaXRzWzJdKQogIGlmIChiICUlIDIgPT0gMSkgYiA8LSBiICsgMQogIHNlcShhLCBiLCBieSA9IDIpCn0KYGBgCgoKYGBge3IgRnVuY3Rpb25zXzJ9CmdldC5nZyA8LSBmdW5jdGlvbihtdHJ4LCBjb2x1bS5uYW1lcywgYXhpcy5sYWJzLCB0aXRyZSwKICAgICAgICAgICAgICAgICAgICBtYXJrZXIuY29sLmZhbHNlLCBtYXJrZXIuY29sLnRydWU9IiNCMjAwMDAiLCBtYXJrZXIuYWxwaGE9MSwgdHRhYmxlKSB7CgogIHR0YWJsZTIgPC0gZHBseXI6OnNlbGVjdCh0dGFibGUsIFBST0JFSUQsIFNZTUJPTCwgYWRqLlAuVmFsKSAlPiUgCiAgICBkcGx5cjo6Z3JvdXBfYnkoUFJPQkVJRCkgJT4lCiAgICBkcGx5cjo6c2xpY2Uod2hpY2gubWluKGFkai5QLlZhbCkpICU+JSAKICAgIGRwbHlyOjp1bmdyb3VwKC4pCgogIGRmIDwtIG10cnhbLGNvbHVtLm5hbWVzXSAlPiUgCiAgICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKGF4aXMubGFicykgJT4lIAogICAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlBST0JFSUQiKQogIAogIGRmMiA8LSBtZXJnZSh4PXR0YWJsZTIsIHk9ZGYsIGJ5PSJQUk9CRUlEIiwgYWxsLng9RkFMU0UsIGFsbC55PVRSVUUpICU+JSAKICAgIGRwbHlyOjptdXRhdGUocC5vayA9IGFkai5QLlZhbCA8PSAwLjA1KSAlPiUgCiAgICBkcGx5cjo6bXV0YXRlKHAub2sgPSBhcy5jaGFyYWN0ZXIocC5vaykpICU+JSAKICAgIGRwbHlyOjptdXRhdGUocC5vayA9IGZhY3RvcihwLm9rLCBsZXZlbHM9YygiRkFMU0UiLCAiVFJVRSIpKSkgJT4lIAogICAgZHBseXI6Om11dGF0ZShJRCA9IHBhc3RlMChTWU1CT0wsICIgKCIsIFBST0JFSUQsICIpIikpICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoLVBST0JFSUQsIC1TWU1CT0wsIC1hZGouUC5WYWwpICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoSUQsIGV2ZXJ5dGhpbmcoKSkKCiAgcmVzIDwtIGRmMiAlPiUgCiAgICBnZ3Bsb3QoYWVzX3N0cmluZyh4PWF4aXMubGFic1sxXSwgeT1heGlzLmxhYnNbMl0pKSArCiAgICBnZW9tX3BvaW50KGFlcyh0ZXh0PUlELCBjb2xvcj1wLm9rKSwgYWxwaGE9bWFya2VyLmFscGhhKSArICMgY29sb3I9bWFya2VyLmNvbC5mYWxzZSwKICAgICMgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZT0icCDiiaQgMC4wNSIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhtYXJrZXIuY29sLmZhbHNlLCBtYXJrZXIuY29sLnRydWUpLCBuYW1lPSJwIOKJpCAwLjA1IikgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9YyhtaW4obXRyeCksIG1heChtdHJ4KSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPWMobWluKG10cngpLCBtYXgobXRyeCkpKSArCiAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yPSJncmV5MjUiKSArCiAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAtbG9nMigxLjc1KSwgc2xvcGUgPSAxLCBjb2xvcj0iZ3JleTI1IiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICAgIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IGxvZzIoMS43NSksIHNsb3BlID0gMSwgY29sb3I9ImdyZXkyNSIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgICBsYWJzKHRpdGxlID0gdGl0cmUpCiAgcmVzCn0KYGBgCgojIyBMb2FkIGRhdGEKIyMjIExvYWQgbWVhbiBleHByZXNzaW9uIGRhdGEgIApUYWJsZSBpbmNsdWRlcyBwcm9iZSBJRHMsIGdlbmUgc3ltYm9scyBhbmQgZ2VuZSBuYW1lcy4gIApQcm9iZSBJRHMgYW5kIHN5bWJvbHMgYXJlIG5vdCB1bmlxdWUgKGR1ZSB0byBnZW5lIHN5bWJvbCBtYXBwaW5nKS4gIAoKYGBge3IgUmVhZCBtZWFuIGV4cHIsIGNsYXNzLm91dHB1dD0idHh0X291dHB1dCJ9Cm1lYW4uZXhwci5maWxlIDwtICIuL2RhdGEvMDFfUmF3X0RhdGFfUHJvY2Vzc2luZy5SbWQuZXhwcl9tZWFuLnR4dCIKbWF0cml4LmRmLm1lYW4gPC0gcmVhZC50YWJsZShtZWFuLmV4cHIuZmlsZSwgc2VwPSJcdCIsIGhlYWRlcj1ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLVNZTUJPTCwgLUdFTkVOQU1FKSAlPiUgCiAgZHBseXI6OmRpc3RpbmN0KFBST0JFSUQsIC5rZWVwX2FsbD1UUlVFKSAlPiUgCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoIlBST0JFSUQiKQpjYXQoIkZpbGUgcmVhZDoiLCBtZWFuLmV4cHIuZmlsZSkKcm0obWVhbi5leHByLmZpbGUpCmBgYAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KaGVhZChtYXRyaXguZGYubWVhbikKYGBgCgoKIyMjIExvYWQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHByb2JlcyAoZWZmZWN0IG9mIE1NUykgIApgYGB7ciBSZWFkIERFIHByb2JlcywgY2xhc3Mub3V0cHV0PSJ0eHRfb3V0cHV0In0KIyBsaXN0LmZpbGVzKCJkYXRhIikKZGlmZi5wcm9iZXMuZmlsZSA8LSAiLi9kYXRhLzAyX1N1cHBsX1RhYmxlXzAxLlJtZC5ERXByb2Jlcy5SRFMiCnN0b3BpZm5vdChmaWxlLmV4aXN0cyhkaWZmLnByb2Jlcy5maWxlKSkKdGVzdC5yZXN1bHRzLnByb2JlcyA8LSByZWFkUkRTKGRpZmYucHJvYmVzLmZpbGUpCmNhdCgiRmlsZSByZWFkOiIsIGRpZmYucHJvYmVzLmZpbGUpCnJtKGRpZmYucHJvYmVzLmZpbGUpCmBgYAoKYGBge3IgcmVzdWx0cz0iYXNpcyJ9CnggPC0gcGFzdGUodXRpbHM6OmNhcHR1cmUub3V0cHV0KHN0cih0ZXN0LnJlc3VsdHMucHJvYmVzKSksIGNvbGxhcHNlPSI8YnI+XG4iLCBzZXA9IiIpCmRldGFpbHM6OmRldGFpbHMoeCwgc3VtbWFyeT0iU2hvdyBzdW1tYXJ5IG9mIERFIHByb2JlcyIsIGxhbmc9TlVMTCkKcm0oeCkKYGBgCgoKIyMjIExvYWQgdG9wdGFibGVzICAKYGBge3IgUmVhZCB0b3B0YWJsZXMsIGNsYXNzLm91dHB1dD0idHh0X291dHB1dCJ9CiMgbGlzdC5maWxlcygpCnR0LmZpbGUgPC0gIlN1cHBsZW1lbnRhbF9EYXRhXzEueGxzeCIKc3RvcGlmbm90KGZpbGUuZXhpc3RzKHR0LmZpbGUpKQp0dC5zaGVldC5uYW1lcyA8LSBvcGVueGxzeDo6Z2V0U2hlZXROYW1lcyh0dC5maWxlKQojIHR0LnNoZWV0Lm5hbWVzCiMgImtvLmN0cmwudnMud3QuY3RybCIgImtvLm1tcy52cy53dC5tbXMiICAgInd0Lm1tcy52cy53dC5jdHJsIiAgImtvLm1tcy52cy5rby5jdHJsIgpnZXQueGxzeC5kYXRhIDwtIGZ1bmN0aW9uKGZpbCwgc2hlZXQpIHsKICBvcGVueGxzeDo6cmVhZC54bHN4KHhsc3hGaWxlID0gZmlsLCBzaGVldD1zaGVldCkKfQp0dC5saXN0IDwtIGxhcHBseSh0dC5zaGVldC5uYW1lcywgZnVuY3Rpb24odGhlLnNoZWV0KSB7CiAgcmVzIDwtIGdldC54bHN4LmRhdGEoZmlsPXR0LmZpbGUsIHNoZWV0PXRoZS5zaGVldCkgJT4lIAogICAgZHBseXI6OnNlbGVjdChQUk9CRUlELCBTWU1CT0wsIGxvZ0ZDLCBhZGouUC5WYWwpCiAgcmVzCn0pICU+JSAKICBzZXRfbmFtZXModHQuc2hlZXQubmFtZXMpCmNhdCgiRmlsZSByZWFkOiIsIHR0LmZpbGUpCnJtKHR0LmZpbGUsIHR0LnNoZWV0Lm5hbWVzKQpgYGAKCgpgYGB7ciByZXN1bHRzPSJhc2lzIn0KeSA8LSBwYXN0ZSh1dGlsczo6Y2FwdHVyZS5vdXRwdXQoc3RyKHR0Lmxpc3QpKSwgY29sbGFwc2U9Ijxicj5cbiIsIHNlcD0iIikKZGV0YWlsczo6ZGV0YWlscyh5LCBzdW1tYXJ5PSJTaG93IHN1bW1hcnkgb2YgdG9wdGFibGVzIGxpc3QiLCBsYW5nPU5VTEwpCnJtKHkpCmBgYAoKCiMjIFBsb3QgcHJvYmVzIHN1cHByZXNzZWQgT1IgaW5kdWNlZCBieSBNTVMgaW4gd2lsZC10eXBlIE9SIGtub2Nrb3V0ICAgIAojIyMgU2VsZWN0IHByb2JlcyB0byBwbG90CmBgYHtyIFNlbGVjdCBnZW5lcyB0byBwbG90LCBjbGFzcy5vdXRwdXQ9InR4dF9vdXRwdXQifQp3dC5rby5kb3duLnVwIDwtIHNvcnQodW5pcXVlKHVubGlzdCh0ZXN0LnJlc3VsdHMucHJvYmVzKSkpCnN0b3BpZm5vdCghYW55KGlzLm5hKHd0LmtvLmRvd24udXApKSkKY2F0KCJQcm9iZXMgc2VsZWN0ZWQ6IiwgbGVuZ3RoKHd0LmtvLmRvd24udXApKQpgYGAKCgoKYGBge3IgcmVzdWx0cz0iaGlkZSJ9CiMgbWF0cml4LmRmLm1lYW5bMTo0LDE6NF0KbXgud3Qua28uZG93bi51cCA8LSBtYXRyaXguZGYubWVhblt3dC5rby5kb3duLnVwLF0KZGltKG14Lnd0LmtvLmRvd24udXApCmBgYAoKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmdnLjYuNCA8LSBnZXQuZ2cobXRyeD1teC53dC5rby5kb3duLnVwLAogICAgICAgY29sdW0ubmFtZXMgPSBjKCJXdF9DdHJsIiwgIktvX0N0cmwiKSwKICAgICAgIGF4aXMubGFicyA9IGMoIldUIiwgIktPIiksCiAgICAgICB0aXRyZSA9ICJDb250cm9sOiBLbm9ja291dCB2ZXJzdXMgV2lsZC10eXBlIiwKICAgICAgIG1hcmtlci5jb2wuZmFsc2UgPSAiIzAwNUFCNSIsICMgYnBbM10KICAgICAgIG1hcmtlci5jb2wudHJ1ZSA9ICIjREMzMjIwIiwKICAgICAgIG1hcmtlci5hbHBoYT0wLjUsCiAgICAgICB0dGFibGU9dHQubGlzdCRrby5jdHJsLnZzLnd0LmN0cmwpCmdnLjYuNGIgPC0gZ2cuNi40ICsgCiAgdGhlbWVfY2xhc3NpYygpICsKICBjb29yZF9lcXVhbCgpCmdncGxvdGx5KGdnLjYuNGIpCmBgYAoKIyMgU2F2ZSBwbG90ICAKYGBge3IgY2xhc3Mub3V0cHV0PSJ0eHRfb3V0cHV0In0Kb3V0LmZpbGUucGRmIDwtICJGaWd1cmVfUzFfQi5wZGYiCmdnc2F2ZShmaWxlbmFtZT1vdXQuZmlsZS5wZGYsIHBsb3QgPSBnZy42LjRiLCB3aWR0aCA9IDEwLCBoZWlnaHQ9MTAsIHVuaXRzID0gImNtIikKY2F0KCJTYXZlZDoiLCBvdXQuZmlsZS5wZGYpCmBgYAoKCiMjIFNlc3Npb24gaW5mbyAgCgo8YnV0dG9uIGNsYXNzPSJidXR0b24iIG9uY2xpY2s9Im15RnVuY3Rpb24oJ0RJVl8xJykiPlNob3cvaGlkZSBzZXNzaW9uIGluZm88L2J1dHRvbj4KPGRpdiBpZD0iRElWXzEiIGNsYXNzPSJkaXZfZGVmYXVsdF9oaWRlIj4KCmBgYHtyIFNFU1NJT04gSU5GTyBEQVRFLCByZXN1bHRzPSJhc2lzIn0KY2F0KCJEYXRlOiIsIGZvcm1hdChTeXMudGltZSgpLCAiJWEgJWQtJWItJVkgJUg6JU06JVMiKSwgIjxicj5cbiIpCmBgYAoKYGBge3IgcHJpbnRfc2Vzc2lvbl9pbmZvLCBSLm9wdGlvbnM9bGlzdCh3aWR0aD03MCl9CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGAKPC9kaXY+CiAgCmBgYHtqc30KdmFyIGRpdnNUb0hpZGUgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJkaXZfZGVmYXVsdF9oaWRlIik7CmZvcih2YXIgaSA9IDA7IGkgPCBkaXZzVG9IaWRlLmxlbmd0aDsgaSsrKQp7CiAgZGl2c1RvSGlkZVtpXS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwp9CmBgYAoKCgo=